package plus.decl;

import java.util.*;

import plus.Gripe;
import plus.M_User;
import plus.Struct;
import plus.Symbol;
import plus.TEnv;
import plus.TS_Record;
import plus.Type;
import plus.TypeSym;

public class D_Record extends Declaration {
	final TS_Record ts;
	final Template tpl;
	final List<PT_Group> fields;
	public D_Record(Template tpl, List<PT_Group> fields, boolean mayNil) {
		this.tpl = tpl;
		ts = new TS_Record(tpl, mayNil);
		this.fields = fields;
	}
	public void define() {
		// Basic process:
		// Build a "Struct" with the appropriate field names,
		// and build a prototype "S_Record" solution with the
		// fields filled in using the appropriate type.
		assert ts.struct == null;
		ts.struct = new Struct();
		TEnv.enterKappa(tpl);
		for (PT_Group g:fields) {
			if (g.typespec == null) {
				for (String n:g.names) ts.struct.introduce_field(n, Type.variable());
			} else {
				Type t = g.typespec.interpret();
				for (String n:g.names) ts.struct.introduce_field(n, t);
			}
		}
		TEnv.exit();
	}
	public void declare() {
		Symbol<TypeSym> probe = TEnv.findType(tpl.sym.name);
		if (probe == null) {
			TEnv.add(tpl.sym);
			tpl.sym.definition = ts;
		} else {
			// Arguably, the said type name should not already exist.
			Gripe.lineNr = tpl.sym.lineNr;
			Gripe.context = this;
			throw new Gripe("Cannot redefine type "+probe);
		}
	}
	public void export() {
		M_User.current.types.enter(tpl.sym);
	}
	public String toString() { return "Record definition for "+tpl; }
}
